package com.startx.core.tools;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.apache.log4j.Logger;
import org.springframework.util.StringUtils;

/**
 * xml Writer工具实现
 * 
 * @author Administrator
 *
 */
public class XmlWriter {

	private StringBuffer  buffer = new StringBuffer();
	private Stack<String> endList = new Stack<>();
	private static final Logger L = Logger.getLogger(XmlWriter.class);
	/**
	 * <
	 */
	private static final String LT = "<"; 
	/**
	 * </
	 */
	private static final String LTD = "</"; 
	/**
	 * >
	 */
	private static final String GT = ">"; 
	/**
	 * Value<Start><End>
	 */
	private static final String VS = "<value>";
	private static final String VE = "</value>";
	/**
	 * SPACE SPLIT
	 */
	private static final String SPACE = " ";
	/**
	 * EQService
	 */
	private static final String EQS = "=\"";
	private static final String EQE = "\"";

	/**
	 * 创建xml文档对象
	 * @return
	 */
	public static XmlWriter startXml() {
		return new XmlWriter();
	}
	
	public XmlWriter() {
		//buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
	}
	
	/**
	 * 写入root根路径
	 * @param obj
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public XmlWriter writeObject(Object obj) {
		
		if(obj == null) {
			return this;
		}
		
		if(isList(obj.getClass())) {
			
			for(Object value:(List<Object>)obj) {
				writeObject(value);
			}
			
		} else {
			String root = obj.getClass().getSimpleName().toLowerCase();
			
			buffer.append(LT+root+GT);
			writeField(obj);
			buffer.append(LTD+root+GT);
		}
		
		return this;
	}
	
	/**
	 * 写入Object
	 * @param obj
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private XmlWriter writeField(Object obj) {
		
		try {
			if (obj != null) {
				
				Class<? extends Object> clz = obj.getClass();
				
				if(isList(clz)) {
					for(Object value:(List<Object>)obj) {
						writeField(value);
					}
				} else {
					
					Field[] fields = clz.getDeclaredFields();
					for(Field field:fields) {
						fieldLoop(obj, field);
					}
				}
			}
			
		} catch (Exception e) {
			L.fatal(e.getMessage());
			e.printStackTrace();
		}
		
		return this;
	}

	/**
	 * fild循环体
	 */
	@SuppressWarnings("unchecked")
	private void fieldLoop(Object obj, Field field) throws IllegalAccessException {
		field.setAccessible(true);
		Class<?> type = field.getType();
		if(isBaseType(type)) {
			
			buffer.append(LT+field.getName()+GT);
			buffer.append(field.get(obj));
			buffer.append(LTD+field.getName()+GT);
		} else if(isList(type)) {
			
			buffer.append(LT+field.getName()+GT);
			
			List<Object> valueList = (List<Object>) field.get(obj);
			
			if(valueList == null) {
				return;
			}
			
			for(Object value:valueList) {
				if(!isBaseType(value.getClass())) {
					writeField(value);
				} else {
					buffer.append(VS);
					buffer.append(value);
					buffer.append(VE);
				}
			}
			
			buffer.append(LTD+field.getName()+GT);
			
		} else {
			buffer.append(LT+field.getName()+GT);
			writeField(field.get(obj));
			buffer.append(LTD+field.getName()+GT);
		}
	}
	
	/**
	 * 检测是否是基本数据类型
	 * @param clz
	 * @return
	 */
	private boolean isBaseType(Class<?> clz) {
		if(clz == String.class 
			|| clz == int.class || clz == Integer.class
			|| clz == short.class || clz == Short.class
			|| clz == long.class || clz == Long.class
			|| clz == boolean.class || clz == Boolean.class
			|| clz == char.class) {
			return true;
		} 
		
		return false;
	}
	
	/**
	 * 是否是集合类型
	 * @param clz
	 * @return
	 */
	private boolean isList(Class<?> clz) {
		if(clz == List.class 
			|| clz == ArrayList.class) {
			return true;
		}
		
		return false;
	}
	
	/**
	 * 写入节点
	 * @param element  节点名称
	 * @param isEnd    是否封闭
	 * @return
	 */
	public XmlWriter writeElement(String element,boolean isEnd) {
		if (!StringUtils.isEmpty(element)) {
			buffer.append(LT + element + GT);
			if(!isEnd) {
				endList.push(LTD + element + GT);
			} else {
				buffer.append(LTD + element + GT);
			}
		}

		return this;
	}
	
	/**
	 * 写入节点
	 * @param element 节点名称
	 * @param value   节点值
	 * @param isEnd   是否结束
	 * @return
	 */
	public XmlWriter writeElement(String element, String value,boolean isEnd) {

		if (!StringUtils.isEmpty(element)) {

			buffer.append(LT + element + GT);
			if (!StringUtils.isEmpty(value)) {
				buffer.append(value);
			}
			
			if(!isEnd) {
				endList.push(LTD + element + GT);
			} else {
				buffer.append(LTD + element + GT);
			}
		}

		return this;
	}
	
	/**
	 * 写入节点
	 * @param element       节点名称
	 * @param value         节点值
	 * @param attributes    节点属性
	 * @param isEnd         是否结束
	 * @return
	 */
	public XmlWriter writeElement(String element, String value,Map<String,String> attributes,boolean isEnd) {

		if (!StringUtils.isEmpty(element)) {

			
			buffer.append(LT + element);
			writeAttribute(attributes);
			buffer.append(GT);
			if (!StringUtils.isEmpty(value)) {
				buffer.append(value);
			}

			if(!isEnd) {
				endList.push(LTD + element + GT);
			} else {
				buffer.append(LTD + element + GT);
			}
		}

		return this;
	}

	/**
	 * 写入属性
	 * @param attributes
	 */
	private void writeAttribute(Map<String, String> attributes) {
		for(String key:attributes.keySet()) {
			buffer.append(SPACE);
			buffer.append(key);
			buffer.append(EQS);
			buffer.append(attributes.get(key));
			buffer.append(EQE);
		}
	}

	/**
	 * 写入xml结束
	 * @return
	 */
	public String endXml() {

		while (endList.size() > 0) {
			buffer.append(endList.pop());
		}

		return buffer.toString();
	}
}